Validation in Java Applications

您所在的位置:网站首页 automating checks of *handcrafted* word tables with Validation in Java Applications

Validation in Java Applications

2023-08-28 04:25| 来源: 网络整理| 查看: 265

Often, I have seen projects that didn't appear to have any conscious strategy for data validation. Their teams worked under the great pressure of deadlines, unclear requirements, and just didn't have enough time to make validation in a proper and consistent way. So, data validation code could be found everywhere — in Javascript snippets, Java screen controllers, business logic beans, domain model entities, database constraints, and triggers. This code was full of if-else statements, throwing different unchecked exceptions, and making it hard to find a place where data could be validated. So, after a while, when the project grew up enough, it became quite hard and expensive to keep these validations consistent and following requirements, which, as I've said, are often fuzzy.

Is there a path for data validation in an elegant, standard, and concise way? Is there a way that doesn't fall into unreadability, helps us to keep most of the data validation logic together, and has most of the code already done for us by developers of popular Java frameworks?

Yes, there is.

For us, developers of the CUBA Platform, it is very important to let our users follow the best practices. We believe that the validation code should be:

Reusable and following the DRY principle; Expressed in a clear and natural way; Placed in the place where developers expect it to see; Able to check data from different data sources: user input, SOAP or REST calls, etc. Aware of concurrency; Called implicitly by the application, without the need to call the checks manually; Showing clear, localized messages to a user using concise designed dialogs; And, following standards.

In this article, I'll be using an application based on the CUBA Platform for all examples. However, since CUBA is based on Spring and EclipseLink, most examples will work for any other Java framework that supports JPA and the bean validation standard.

DB Constraints Validations

Perhaps, the most common and straightforward way of data validation uses DB-level constraints, such as a required flag ('not null' fields), string length, unique indexes, and so on. This way is very natural for enterprise applications, as this class of software is usually heavily data-centric. However, even here, developers do mistakes, defining constraints separately for each tier of an application. This problem is often caused by splitting responsibilities between developers.

Let's take an example that most of you have probably faced. If a spec says that the passport field should have 10 digits in its number, most likely, it will be checked everywhere — by the DB architect in DDL, by the backend developer in the corresponding Entity and REST services, and finally, by the UI developer in client source code. Later on, this requirement changes and the size of the field grows up to 15 digits. Tech Support changes the DB constraint, but for a user, it means nothing since the client side check will not be passed anyway.

Everybody knows the way to avoid this problem — validations must be centralized! In CUBA, this central point of such kind of validation is JPA annotations over entities. Based on this meta information, CUBA Studio generates the correct DDL scripts and applies corresponding validators on the client side.

If JPA annotations get changed, CUBA updates DDL scripts and generates migration scripts, so next time you deploy your project, new JPA-based limitations will be applied to your application's UI and DB.

Despite simplicity and implementation that spans up to DB level and is completely bullet-proof, JPA annotations are limited by the simplest cases that can be expressed in DDL standard without involving DB-specific triggers or stored procedures. So, JPA-based constraints can ensure that the entity field is unique or mandatory or can define a maximum length for a varchar column. Also, you can define a unique constraint to the combination of columns with the @UniqueConstraint annotation. But, this is pretty much it.

However, in the cases that require more complex validation logic, like checking for maximum and minimum values of a field, validating with an expression, or performing a custom check that is specific to your application, we need to utilize the well-known approach called Bean validation.

Bean Validation

All we know, Bean validation is a good practice to follow standards, which normally have a long lifecycle and are battle-proven on thousands of projects. Java Bean validation is an approach that is set in stone in JSR 380, 349 and 303, and their implementations: Hibernate Validator and Apache BVal.

Although this approach is familiar to many developers, it's benefits are often underestimated. This is an easy way to add data validations even for legacy projects, which allows you to express your validations in a clear, straightforward, and reliable way that is as close to your business logic as possible.

Using the Bean validation approach brings a lot of benefits to your project:

Validation logic is concentrated near your domain model, defining the value and method, and the bean constraint is done in a natural way that allows bringing an OOP approach to the next level. The Bean validation standard provides many validation annotations out of the box, like:@NotNull,  @Size, @Min, @Max, @Pattern, @Email, @Past, and a less standard like,@URL@Length, might @ScriptAssert, and many others. You are not limited by predefined constraints and can define your own constraint annotations. You can make a new annotation by combining others or making a brand new one and defining a Java class that will be served as a validator. For example, looking at our previous example, we can define a class-level annotation @ValidPassportNumber to check that the passport number follows the right format, which depends on the country field value. You can put constraints not just on fields and classes but also on methods and method parameters. This is called "validation by contract" and is the topic of a later section.

The CUBA Platform, as well as some other frameworks, calls these Bean validations automatically when a user submits the data, so the user would get the error message instantly if validation fails,  and you don't need to worry about running these Bean validators manually.

Let's take a look at the passport number example once again, but this time, we'd like to add a couple additional constraints on the entity:

Person name should have a length of two or more and be a well-formed name. Regexp is quite complex, but Charles Ogier de Batz de Castelmore Comte d'Artagnan passes the check and R2D2 does not Person height should be in interval: 0 < height


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3